﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ToolTip;

namespace August.UI
{
    public class Cross : ShapeBase
    {
        public event EventHandler<MouseEventArgs> MouseDown;
        public GraphicsPath ScaleGraphicPath = new GraphicsPath();
        public float Radius;
        public float Angle;
        public string Text = "1";
        private object dataContext;
        private float minPix = 0.1f;
        List<PointF> m_pointFsList = new List<PointF>();
        public float MinPix
        {
            get { return minPix; }
            set { minPix = value; }
        }

        private int selectedIndex;

        public int SelectedIndex
        {
            get { return selectedIndex; }
        }


        public object DataContext
        {
            get { return dataContext; }
            set { dataContext = value; }
        }

        public Cross(PointF[] pointFs, float radius, float angle)
        {
            dataContext = pointFs;
            PointFs = pointFs;
            Radius = radius;
            Angle = angle;
        }

        private double[] GetDistance(PointF[] pointA, PointF[] pointB)
        {
            if (pointA.Length != pointB.Length) throw new Exception("getDistance : point length not equal");
            double[] distances = new double[pointA.Length];
            for (int i = 0; i < distances.Length; i++)
            {
                distances[i] = Math.Pow((pointA[i].X - pointB[i].X), 2) + Math.Pow((pointA[i].Y - pointB[i].Y), 2);
                distances[i] = Math.Sqrt(distances[i]);
            }
            return distances;
        }
        internal override bool OnDownPaint(MouseEventArgs e)
        {
            selectedIndex = -1;
            PointF pointFmouseDown = new PointF(e.X, e.Y);
            System.Drawing.Drawing2D.Matrix transform = new Matrix();
            transform.Scale(Parent.Owner.ScaleX, Parent.Owner.ScaleY, System.Drawing.Drawing2D.MatrixOrder.Append);
            transform.Translate(Parent.Owner.OffsetX, Parent.Owner.OffsetY, System.Drawing.Drawing2D.MatrixOrder.Append);
            transform.Invert();
            PointF[] pointFs = new PointF[] { pointFmouseDown };
            transform.TransformPoints(pointFs);
            for (int i = 0; i < m_pointFsList.Count; i++)
            {
                double[] doubles = GetDistance(new PointF[] { m_pointFsList[i] }, new PointF[] { pointFs[0] });
                if (Math.Abs(doubles[0]) < minPix / 2)
                {
                   selectedIndex = PointFs.ToList().FindIndex(t => t == m_pointFsList[i]);
                    
                }
            }



            if (this.DrawGraphicsPath.IsOutlineVisible(e.X, e.Y, new Pen(Color.Empty, DrawLineWidth + 6)))
            {
                m_isSelected = true;
                m_DrawColor = ShapeBase.ColorMouseDown;
                m_mouseDownMovePointFs = new PointF[PointFs.Length];
                PointFs.CopyTo(m_mouseDownMovePointFs, 0);
                int index = -1;
                m_IsSelectedPoint = IsHitPoint(e.X, e.Y, LastPointFs, ref index);
                m_selectedPointIndex = index;
                MouseDown?.Invoke(this, e);
                return true;
            }
            else
                return false;
        }

        protected bool IsHitPoint(int x, int y, PointF[] pointFs, ref int index)
        {
            index = -1;
            for (int k = 0; k < pointFs.Length; k++)
            {
                if (Math.Abs(pointFs[k].X - x) < 6 && Math.Abs(pointFs[k].Y - y) < 6)
                {
                    index = k;
                    return true;
                }
            }
            return false;
        }

        internal override void OnMovePaint(MouseEventArgs e)
        {
            base.OnMovePaint(e);
            if (m_isSelected && IsUserShape)
            {
                Point point = e.Location;
                Matrix matrix = new Matrix();
                matrix.Translate((-m_mouseDownPointF.X + point.X) * 1f / Parent.Owner.ScaleX, (-m_mouseDownPointF.Y + point.Y) * 1f / Parent.Owner.ScaleY);
                m_mouseDownMovePointFs.CopyTo(PointFs, 0);
                matrix.TransformPoints(PointFs);
            }
        }

        internal override void OnWheelPaint(PaintEventArgs e)
        {
            Cross cross = this;
            if (cross.PointFs.Length > 0)
            {
                PointF[] m_pointFs = new PointF[cross.PointFs.Length];
                PointF[] m_pointFs2;
                cross.PointFs.CopyTo(m_pointFs, 0);
                int phi = 1;
                using (System.Drawing.Drawing2D.Matrix transform = new Matrix())
                {
                    PointF[] pointFWindow = new PointF[] { new PointF(0, 0), new PointF(e.ClipRectangle.Width, e.ClipRectangle.Height) };
                    transform.Scale(Parent.Owner.ScaleX,  Parent.Owner.ScaleY, System.Drawing.Drawing2D.MatrixOrder.Append);
                    transform.Translate(Parent.Owner.OffsetX, Parent.Owner.OffsetY, System.Drawing.Drawing2D.MatrixOrder.Append);
                    transform.Invert();
                    transform.TransformPoints(pointFWindow);
                    RectangleF rectancleWindow = new RectangleF(pointFWindow[0].X, pointFWindow[0].Y, pointFWindow[1].X - pointFWindow[0].X, pointFWindow[1].Y - pointFWindow[0].Y);

                    phi = (int)Math.Ceiling(3d / minPix / Parent.Owner.ScaleX);
                    Console.WriteLine($"{phi}");
                    m_pointFsList.Clear();
                    for (int i = 0; i < m_pointFs.Length; i += phi)
                    {
                        if (rectancleWindow.Contains(new PointF() { X = m_pointFs[i].X, Y = m_pointFs[i].Y }))
                        {
                            m_pointFsList.Add(m_pointFs[i]);
                        }
                    }
                    m_pointFs2 = m_pointFsList.ToArray();
                    if (m_pointFs2.Length == 0) return;
                    transform.Invert();
                    transform.TransformPoints(m_pointFs2);
                    cross.TransForm = transform.Clone();
                    cross.LastPointFs = m_pointFs2;
                }
                GraphicsPath graphicsPathCross = new GraphicsPath();
                for (int k = 0; k < m_pointFs2.Length; k += 1)
                {
                    GraphicsPath path = CreateCrossGraphicPath(m_pointFs2[k], cross.Radius, cross.Angle);
                    graphicsPathCross.AddPath(path, false);
                }
                e.Graphics.DrawPath(new Pen(cross.m_DrawColor, cross.DrawLineWidth), graphicsPathCross);
                //e.Graphics.DrawString(Text, new Font("黑体", 9f, FontStyle.Regular), new SolidBrush(cross.DrawColor), new PointF(LastPointFs[0].X + 6, LastPointFs[0].Y - 6));
                cross.DrawRegion = new Region(graphicsPathCross);
                cross.DrawGraphicsPath = graphicsPathCross;
                cross.MoveGraphicPath = graphicsPathCross;
                cross.ScaleGraphicPath = graphicsPathCross;
            }
            base.OnWheelPaint(e);
        }

        private GraphicsPath CreateCrossGraphicPath(PointF pointF, float radius, float angle)
        {
            float L1x1 = pointF.X - radius;
            float L1y1 = pointF.Y;
            float L1x2 = pointF.X + radius;
            float L1y2 = pointF.Y;
            float L2x1 = pointF.X;
            float L2y1 = pointF.Y - radius;
            float L2x2 = pointF.X;
            float L2y2 = pointF.Y + radius;
            PointF[] pointFs = new PointF[4] { new PointF(L1x1, L1y1), new PointF(L1x2, L1y2), new PointF(L2x1, L2y1), new PointF(L2x2, L2y2) };
            Matrix transform = new Matrix();
            transform.RotateAt(angle, pointF);
            transform.TransformPoints(pointFs);

            GraphicsPath graphicsPath1 = new GraphicsPath();
            graphicsPath1.AddLine(pointFs[0], pointFs[1]);
            GraphicsPath graphicsPath2 = new GraphicsPath();
            graphicsPath2.AddLine(pointFs[2], pointFs[3]);
            graphicsPath1.AddPath(graphicsPath2, false);
            return graphicsPath1;
        }
    }
}
